const Koa = require('koa');

class Cube {
  constructor() {
    this.middlewares = [];
  }

  use(middleware) {
    this.middlewares.push(middleware);
  }

  async execute(ctx, next) {
    const middlewareChain = this.middlewares.reduceRight((next, middleware) => {
      return async () => {
        await middleware(ctx, next);
      };
    }, next);
    
    await middlewareChain();
  }
}

// 创建 Koa 实例
const app = new Koa();

// 创建 Cube 实例
const cube = new Cube();

// 添加两个启动时固定加载的中间件
cube.use(async (ctx, next) => {
  console.log('固定中间件AA - 前置');
  await next();
  console.log('固定中间件AA - 后置');
});

cube.use(async (ctx, next) => {
  console.log('固定中间件BB - 前置');
  await next();
  console.log('固定中间件BB - 后置');
});

// 运行时传入的中间件列表
const runtimeMiddlewares = [
  async (ctx, next) => {
    console.log('运行时自定义的中间件A - 前置');
    await next();
    console.log('运行时自定义的中间件A - 后置');
  },
  async (ctx, next) => {
    console.log('运行时自定义的中间件B - 前置');
    await next();
    console.log('运行时自定义的中间件B - 后置');
  },
  async (ctx, next) => {
    console.log('运行时自定义的中间件C - 前置');
    await next();
    console.log('运行时自定义的中间件C - 后置');
  },
];

// 配置中间件执行顺序
const middlewareOrder = [2, 0, 1];

// 根据配置的顺序添加中间件到 Cube 实例
middlewareOrder.forEach(index => {
  cube.use(runtimeMiddlewares[index]);
});

// Koa 应用中间件
app.use(async (ctx, next) => {
  await cube.execute(ctx, next);
});

// 启动 Koa 服务器
app.listen(3000, () => {
  console.log('Koa server is running on port 3000');
});

